home *** CD-ROM | disk | FTP | other *** search
- /*
- ** our include
- */
-
- #include "getbmp.h"
-
- /*
- ** easy access of a char-array as a "structure" (IJG sources v5.0b)
- */
-
- #define UCH(x) \
- ((int) (x))
-
- #define GET_2B(array,offset) \
- ((unsigned int) UCH(array[offset]) + \
- (((unsigned int) UCH(array[offset+1])) << 8))
-
- #define GET_4B(array,offset) \
- ((ULONG) UCH(array[offset]) + \
- (((ULONG) UCH(array[offset+1])) << 8) + \
- (((ULONG) UCH(array[offset+2])) << 16) + \
- (((ULONG) UCH(array[offset+3])) << 24))
-
- /*
- ** get dt attribute(s)
- */
-
- ULONG set_dt_attrs(Object *obj, ULONG data, ...)
- {
- return (SetDTAttrsA(obj,NULL,NULL,(struct TagItem *)&data));
- }
-
- /*
- ** get dt attribute(s)
- */
-
- ULONG get_dt_attrs(Object *obj, ULONG data, ...)
- {
- return (GetDTAttrsA(obj,(struct TagItem *)&data));
- }
-
- /*
- ** expand every bit to a byte
- */
-
- VOID convert_1bit(UBYTE *pixelbuf, UBYTE *outbuf, ULONG width)
- {
- UBYTE *p=outbuf,c;
- int i,j;
-
- for(i=width/8; i>0; i--)
- {
- for(c=*pixelbuf++,j=7; j>=0; j--)
- {
- *p++ = ((c & 0x80) ? 1 : 0);
- c <<= 1;
- }
- }
- if ((i=width%8))
- {
- for(c=*pixelbuf,j=7; i>0; j--,i--)
- {
- *p++ = ((c & 0x80) ? 1 : 0);
- c <<= 1;
- }
- }
- }
-
- /*
- ** expand every 4 bits to a byte
- */
-
- VOID convert_4bit(UBYTE *pixelbuf, UBYTE *outbuf, ULONG width)
- {
- UBYTE *p=outbuf,c;
- int i;
-
- for(i=width/2; i>0; i--)
- {
- c = *pixelbuf++;
- *p++ = (c >> 4); /* ((c & 0xf0) >> 4); */
- *p++ = (c & 0xf);
- }
- if (width & 1)
- {
- c = *pixelbuf; *p = (c >> 4); /* ((c & 0xf0) >> 4); */
- }
- }
-
- /*
- ** perform a simple copy (outbuf is WritePixelLine8() aware..)
- */
-
- VOID convert_8bit(UBYTE *pixelbuf, UBYTE *outbuf, ULONG width)
- {
- CopyMem(pixelbuf,outbuf,width);
- }
-
- /*
- ** create the bitmap
- */
-
- int decode_bmp_picture(Object *obj, APTR pool, BPTR fh, struct BitMapHeader *bmhd, ULONG title)
- {
- register VOID (*convert)(UBYTE *pixelbuf, UBYTE *outbuf, ULONG width) REG(a3);
- struct BitMap *tbm,*bm;
- struct RastPort trp,rp;
- UBYTE *albuff,*buffer,*p;
- ULONG modeid,padwidth,width,height,depth,large;
- int line,index,success=FALSE;
-
- width = bmhd->bmh_Width; height = bmhd->bmh_Height; depth = bmhd->bmh_Depth;
-
- if ((bm=AllocBitMap(width,height,depth,BMF_CLEAR|BMF_DISPLAYABLE,NULL)) != NULL)
- {
- InitRastPort(&rp); rp.BitMap = bm;
-
- if ((tbm=AllocBitMap(width,1,depth,BMF_CLEAR,NULL)) != NULL)
- {
- InitRastPort(&trp); trp.BitMap = tbm;
-
- if ((albuff=AllocPooled(pool,((width+15)&~15))) != NULL)
- {
- padwidth = ((((width * depth) + 31) & ~31) / 8);
-
- large = padwidth * height;
-
- if ((buffer=AllocPooled(pool,large)) != NULL)
- {
- if (Read(fh,buffer,large) != large)
- {
- buffer=NULL;
- }
- }
- else
- {
- buffer=AllocPooled(pool,padwidth); large=0;
- }
-
- if (buffer != NULL)
- {
- convert = convert_1bit;
- if (depth != 1)
- {
- convert = convert_4bit;
- if (depth != 4)
- convert = convert_8bit;
- }
-
- for (line=(height-1),index=0; line>=0; index++,line--)
- {
- if (large)
- p=&buffer[index*padwidth];
- else
- if (Read(fh,(p=buffer),padwidth) != padwidth)
- goto error;
- (*convert)(p,albuff,width);
- WritePixelLine8(&rp,0,line,width,albuff,&trp);
- }
-
- modeid = LORES_KEY;
- if ((UWORD)width >= 640)
- modeid = HIRES;
- if ((UWORD)height >= 400)
- modeid |= LACE;
-
- set_dt_attrs(obj,
- DTA_ObjName, title,
- DTA_NominalHoriz, width,
- DTA_NominalVert, height,
- PDTA_BitMap, bm,
- PDTA_ModeID, modeid,
- TAG_DONE);
-
- success = TRUE;
-
- }
-
- }
- error:
- FreeBitMap(tbm);
- }
-
- if (!success)
- FreeBitMap(bm);
- }
-
- return success;
- }
-
- /*
- ** extract all required information from the bmp header
- */
-
- int read_bmp_header(Object *obj, APTR pool, BPTR fh, struct BitMapHeader *bmhd)
- {
- UBYTE bmpfileheader[14+64],*coltab,*cmap;
-
- #define bmpinfoheader (bmpfileheader+14)
-
- LONG *cregs;
- LONG biCompression;
- LONG biClrUsed;
- LONG biPlanes;
- LONG bfOffBits;
- LONG headerSize;
- LONG bPad;
- LONG cmapentrysize;
- LONG coltabsize;
- int i;
-
- if (Read(fh,bmpfileheader,18) != 18)
- return FALSE;
-
- if (((UWORD)GET_2B(bmpfileheader,0)) != 0x4D42)
- return FALSE;
-
- bfOffBits = (LONG) GET_4B(bmpfileheader,10);
- headerSize = (LONG) GET_4B(bmpinfoheader, 0);
-
- if (headerSize < 12 || headerSize > 64)
- return FALSE;
-
- if (Read(fh,bmpinfoheader+4,headerSize-4) != (headerSize-4))
- return FALSE;
-
- switch(headerSize)
- {
- case 12: /* OS/2 1.x */
- bmhd->bmh_Width = (WORD) GET_2B(bmpinfoheader, 4);
- bmhd->bmh_Height = (WORD) GET_2B(bmpinfoheader, 6);
- biPlanes = GET_2B(bmpinfoheader, 8);
- bmhd->bmh_Depth = (WORD) GET_2B(bmpinfoheader,10);
- biCompression = 0;
- biClrUsed = 0;
- switch (bmhd->bmh_Depth)
- {
- case 1:
- case 4:
- case 8:
- cmapentrysize = 3;
- break;
- case 24:
- cmapentrysize = 0;
- break;
- default:
- cmapentrysize = 0;
- break;
- }
- break;
- case 40: /* Windows 3.x or OS/2 2.x */
- case 64:
- bmhd->bmh_Width = (WORD) GET_4B(bmpinfoheader, 4);
- bmhd->bmh_Height = (WORD) GET_4B(bmpinfoheader, 8);
- biPlanes = GET_2B(bmpinfoheader,12);
- bmhd->bmh_Depth = (WORD) GET_2B(bmpinfoheader,14);
- biCompression = GET_4B(bmpinfoheader,16);
- biClrUsed = GET_4B(bmpinfoheader,32);
- switch (bmhd->bmh_Depth)
- {
- case 1:
- case 4:
- case 8:
- cmapentrysize = 4;
- break;
- case 24:
- cmapentrysize = 0;
- break;
- default:
- cmapentrysize = 0;
- break;
- }
- break;
- default:
- cmapentrysize = 0;
- break;
- }
-
- bmhd->bmh_PageWidth = bmhd->bmh_Width;
- bmhd->bmh_PageHeight = bmhd->bmh_Height;
-
- if (biPlanes != 1 || biCompression != 0 || cmapentrysize == 0)
- return FALSE;
-
- if (biClrUsed <= 0)
- biClrUsed = 1L << bmhd->bmh_Depth;
-
- if (biClrUsed > 256)
- return FALSE;
-
- (void)set_dt_attrs(obj, PDTA_NumColors,(ULONG)biClrUsed, TAG_DONE);
-
- if ((get_dt_attrs(obj, PDTA_ColorRegisters,(ULONG)&cmap,PDTA_CRegs,(ULONG)&cregs, TAG_DONE)) != 2)
- return FALSE;
-
- coltabsize = biClrUsed * cmapentrysize;
-
- if ((coltab=AllocPooled(pool,coltabsize)) == NULL)
- return FALSE;
-
- if (Read(fh,coltab,coltabsize) != coltabsize)
- return FALSE;
-
- /*
- ** do not use "struct ColorRegister" for cmap since with the amiga port
- ** of gcc a sizeof() for this structure is four and not three.. oh well
- */
-
- for(i=0; i<biClrUsed; cmap+=3,cregs+=3,coltab+=cmapentrysize,i++)
- {
- UBYTE r,g,b;
-
- r = coltab[2];
- cmap[0] = r; cregs[0] = r << 24;
- g = coltab[1];
- cmap[1] = g; cregs[1] = g << 24;
- b = coltab[0];
- cmap[2] = b; cregs[2] = b << 24;
- }
-
- bPad = bfOffBits - (14 + headerSize + coltabsize);
-
- for(;bPad>0;)
- {
- LONG size = (bPad < sizeof(bmpfileheader) ? bPad : sizeof(bmpfileheader));
- if (Read(fh,&bmpfileheader[0],size) != size)
- break;
- bPad -= size;
- }
-
- return (bPad == 0 ? TRUE : FALSE);
- }
-
- /*
- ** load the picture
- */
-
- int GetBMP(Class *cl, Object *obj, struct TagItem *attrs)
- {
- struct BitMapHeader *bmhd;
- LONG ioerr;
- APTR pool;
- BPTR fh;
- int success=FALSE;
-
- if ((pool=CreatePool(MEMF_ANY,1024,1024)) != NULL)
- {
- if ((get_dt_attrs(obj, DTA_Handle,&fh,PDTA_BitMapHeader,&bmhd, TAG_DONE) == 2) && fh)
- for(;;)
- {
- ioerr=ERROR_OBJECT_WRONG_TYPE;
- if ((success=read_bmp_header(obj,pool,fh,bmhd)) != FALSE)
- {
- if ((success=decode_bmp_picture(obj,pool,fh,bmhd,GetTagData(DTA_Name,NULL,attrs))) != FALSE)
- break;
- ioerr=ERROR_NO_FREE_STORE;
- }
- SetIoErr(ioerr); break;
- }
- DeletePool(pool);
- }
- return success;
- }
-